home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / 92052tar.gz / 920528.tar / trace.c < prev    next >
C/C++ Source or Header  |  1992-05-14  |  8KB  |  373 lines

  1. /* @(#) $Header: trace.c,v 1.10 92/05/14 13:20:36 deyke Exp $ */
  2.  
  3. /* Packet tracing - top level and generic routines, including hex/ascii
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  */
  6. #include <sys/types.h>
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include <time.h>
  10. #include "global.h"
  11. #ifdef  ANSIPROTO
  12. #include <stdarg.h>
  13. #endif
  14. #include "mbuf.h"
  15. #include "iface.h"
  16. #include "pktdrvr.h"
  17. #include "commands.h"
  18. #include "trace.h"
  19. #include "timer.h"
  20.  
  21. static void ascii_dump __ARGS((FILE *fp,struct mbuf **bpp));
  22. static void ctohex __ARGS((char *buf,int c));
  23. static void fmtline __ARGS((FILE *fp,int addr,char *buf,int len));
  24. static void hex_dump __ARGS((FILE *fp,struct mbuf **bpp));
  25. static void showtrace __ARGS((struct iface *ifp));
  26.  
  27. /* Redefined here so that programs calling dump in the library won't pull
  28.  * in the rest of the package
  29.  */
  30. static char nospace[] = "No space!!\n";
  31.  
  32. struct tracecmd Tracecmd[] = {
  33.     "input",        IF_TRACE_IN,    IF_TRACE_IN,
  34.     "-input",       0,              IF_TRACE_IN,
  35.     "output",       IF_TRACE_OUT,   IF_TRACE_OUT,
  36.     "-output",      0,              IF_TRACE_OUT,
  37.     "broadcast",    0,              IF_TRACE_NOBC,
  38.     "-broadcast",   IF_TRACE_NOBC,  IF_TRACE_NOBC,
  39.     "raw",          IF_TRACE_RAW,   IF_TRACE_RAW,
  40.     "-raw",         0,              IF_TRACE_RAW,
  41.     "ascii",        IF_TRACE_ASCII, IF_TRACE_ASCII|IF_TRACE_HEX,
  42.     "-ascii",       0,              IF_TRACE_ASCII|IF_TRACE_HEX,
  43.     "hex",          IF_TRACE_HEX,   IF_TRACE_ASCII|IF_TRACE_HEX,
  44.     "-hex",         IF_TRACE_ASCII, IF_TRACE_ASCII|IF_TRACE_HEX,
  45.     "off",          0,              0xffff,
  46.     NULLCHAR,       0,              0
  47. };
  48.  
  49. void
  50. dump(ifp,direction,type,bp)
  51. register struct iface *ifp;
  52. int direction;
  53. unsigned type;
  54. struct mbuf *bp;
  55. {
  56.     struct mbuf *tbp;
  57.     void (*func) __ARGS((FILE *,struct mbuf **,int));
  58.     int16 size;
  59.     time_t timer;
  60.     char *cp;
  61.  
  62.     if(ifp == NULL || (ifp->trace & direction) == 0)
  63.         return; /* Nothing to trace */
  64.  
  65.     switch(direction){
  66.     case IF_TRACE_IN:
  67.         if((ifp->trace & IF_TRACE_NOBC)
  68.          && (Tracef[type].addrtest != NULLFP)
  69.          && (*Tracef[type].addrtest)(ifp,bp) == 0)
  70.             return;         /* broadcasts are suppressed */
  71.         timer = secclock();
  72.         cp = ctime(&timer);
  73.         cp[24] = '\0';
  74.         fprintf(ifp->trfp,"\n%s - %s recv:\n",cp,ifp->name);
  75.         break;
  76.     case IF_TRACE_OUT:
  77.         timer = secclock();
  78.         cp = ctime(&timer);
  79.         cp[24] = '\0';
  80.         fprintf(ifp->trfp,"\n%s - %s sent:\n",cp,ifp->name);
  81.         break;
  82.     }
  83.     if(bp == NULLBUF || (size = len_p(bp)) == 0){
  84.         fprintf(ifp->trfp,"empty packet!!\n");
  85.         return;
  86.     }
  87.  
  88.     if(type < NCLASS)
  89.         func = Tracef[type].tracef;
  90.     else
  91.         func = NULLVFP;
  92.  
  93.     dup_p(&tbp,bp,0,size);
  94.     if(tbp == NULLBUF){
  95.         fprintf(ifp->trfp,nospace);
  96.         return;
  97.     }
  98.     if(func != NULLVFP)
  99.         (*func)(ifp->trfp,&tbp,1);
  100.     if(ifp->trace & IF_TRACE_ASCII){
  101.         /* Dump only data portion of packet in ascii */
  102.         ascii_dump(ifp->trfp,&tbp);
  103.     } else if(ifp->trace & IF_TRACE_HEX){
  104.         /* Dump entire packet in hex/ascii */
  105.         free_p(tbp);
  106.         dup_p(&tbp,bp,0,len_p(bp));
  107.         if(tbp != NULLBUF)
  108.             hex_dump(ifp->trfp,&tbp);
  109.         else
  110.             fprintf(ifp->trfp,nospace);
  111.     }
  112.     free_p(tbp);
  113. }
  114.  
  115. /* Dump packet bytes, no interpretation */
  116. void
  117. raw_dump(ifp,direction,bp)
  118. struct iface *ifp;
  119. int direction;
  120. struct mbuf *bp;
  121. {
  122.     struct mbuf *tbp;
  123.  
  124.     /* Dump entire packet in hex/ascii */
  125.     fprintf(ifp->trfp,"\n******* raw packet dump (%s %s)\n",
  126.         ((direction & IF_TRACE_OUT) ? "send" : "recv"),ifp->name);
  127.     dup_p(&tbp,bp,0,len_p(bp));
  128.     if(tbp != NULLBUF)
  129.         hex_dump(ifp->trfp,&tbp);
  130.     else
  131.         fprintf(ifp->trfp,nospace);
  132.     fprintf(ifp->trfp,"*******\n");
  133.     free_p(tbp);
  134.     return;
  135. }
  136.  
  137. /* Dump an mbuf in hex */
  138. static void
  139. hex_dump(fp,bpp)
  140. FILE *fp;
  141. register struct mbuf **bpp;
  142. {
  143.     int16 n;
  144.     int16 address;
  145.     char buf[16];
  146.  
  147.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  148.         return;
  149.  
  150.     address = 0;
  151.     while((n = pullup(bpp,buf,sizeof(buf))) != 0){
  152.         fmtline(fp,address,buf,n);
  153.         address += n;
  154.     }
  155. }
  156. /* Dump an mbuf in ascii */
  157. static void
  158. ascii_dump(fp,bpp)
  159. FILE *fp;
  160. register struct mbuf **bpp;
  161. {
  162.     int c;
  163.     register int16 tot;
  164.  
  165.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  166.         return;
  167.  
  168.     tot = 0;
  169.     while((c = PULLCHAR(bpp)) != -1){
  170.         if((tot % 64) == 0)
  171.             fprintf(fp,"%04x  ",tot);
  172.         putc(isprint(uchar(c)) ? c : '.',fp);
  173.         if((++tot % 64) == 0)
  174.             fprintf(fp,"\n");
  175.     }
  176.     if((tot % 64) != 0)
  177.         fprintf(fp,"\n");
  178. }
  179. /* Print a buffer up to 16 bytes long in formatted hex with ascii
  180.  * translation, e.g.,
  181.  * 0000: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f  0123456789:;<=>?
  182.  */
  183. static void
  184. fmtline(fp,addr,buf,len)
  185. FILE *fp;
  186. int16 addr;
  187. char *buf;
  188. int16 len;
  189. {
  190.     char line[80];
  191.     register char *aptr,*cptr;
  192.     register char c;
  193.  
  194.     memset(line,' ',sizeof(line));
  195.     ctohex(line,(int16)hibyte(addr));
  196.     ctohex(line+2,(int16)lobyte(addr));
  197.     aptr = &line[6];
  198.     cptr = &line[55];
  199.     while(len-- != 0){
  200.         c = *buf++;
  201.         ctohex(aptr,(int16)uchar(c));
  202.         aptr += 3;
  203.         c &= 0x7f;
  204.         *cptr++ = isprint(uchar(c)) ? c : '.';
  205.     }
  206.     *cptr++ = '\n';
  207.     fwrite(line,1,(unsigned)(cptr-line),fp);
  208. }
  209. /* Convert byte to two ascii-hex characters */
  210. static void
  211. ctohex(buf,c)
  212. register char *buf;
  213. register int16 c;
  214. {
  215.     static char hex[] = "0123456789abcdef";
  216.  
  217.     *buf++ = hex[hinibble(c)];
  218.     *buf = hex[lonibble(c)];
  219. }
  220.  
  221. /* Modify or displace interface trace flags */
  222. int
  223. dotrace(argc,argv,p)
  224. int argc;
  225. char *argv[];
  226. void *p;
  227. {
  228.     struct iface *ifp;
  229.     struct tracecmd *tp;
  230.  
  231.     if(argc < 2){
  232.         for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  233.             showtrace(ifp);
  234.         return 0;
  235.     }
  236.     if((ifp = if_lookup(argv[1])) == NULLIF){
  237.         printf("Interface %s unknown\n",argv[1]);
  238.         return 1;
  239.     }
  240.     if(argc == 2){
  241.         showtrace(ifp);
  242.         return 0;
  243.     }
  244.     /* MODIFY THIS TO HANDLE MULTIPLE OPTIONS */
  245.     if(argc >= 3){
  246.         for(tp = Tracecmd;tp->name != NULLCHAR;tp++)
  247.             if(strncmp(tp->name,argv[2],strlen(argv[2])) == 0)
  248.                 break;
  249.         if(tp->name != NULLCHAR)
  250.             ifp->trace = (ifp->trace & ~tp->mask) | tp->val;
  251.         else
  252.             ifp->trace = htoi(argv[2]);
  253.     }
  254.     /* Always default to stdout unless trace file is given */
  255.     if(ifp->trfp != NULLFILE && ifp->trfp != stdout)
  256.         fclose(ifp->trfp);
  257.     ifp->trfp = stdout;
  258.     if(ifp->trfile != NULLCHAR)
  259.         free(ifp->trfile);
  260.     ifp->trfile = NULLCHAR;
  261.  
  262.     if(argc >= 4){
  263.         if((ifp->trfp = fopen(argv[3],APPEND_TEXT)) == NULLFILE){
  264.             printf("Can't write to %s\n",argv[3]);
  265.             ifp->trfp = stdout;
  266.         } else {
  267.             ifp->trfile = strdup(argv[3]);
  268.         }
  269.     }
  270.     showtrace(ifp);
  271.     return 0;
  272. }
  273. /* Display the trace flags for a particular interface */
  274. static void
  275. showtrace(ifp)
  276. register struct iface *ifp;
  277. {
  278.     if(ifp == NULLIF)
  279.         return;
  280.     printf("%s:",ifp->name);
  281.     if(ifp->trace & (IF_TRACE_IN | IF_TRACE_OUT | IF_TRACE_RAW)){
  282.         if(ifp->trace & IF_TRACE_IN)
  283.             printf(" input");
  284.         if(ifp->trace & IF_TRACE_OUT)
  285.             printf(" output");
  286.  
  287.         if(ifp->trace & IF_TRACE_NOBC)
  288.             printf(" - no broadcasts");
  289.  
  290.         if(ifp->trace & IF_TRACE_HEX)
  291.             printf(" (Hex/ASCII dump)");
  292.         else if(ifp->trace & IF_TRACE_ASCII)
  293.             printf(" (ASCII dump)");
  294.         else
  295.             printf(" (headers only)");
  296.  
  297.         if(ifp->trace & IF_TRACE_RAW)
  298.             printf(" Raw output");
  299.  
  300.         if(ifp->trfile != NULLCHAR)
  301.             printf(" trace file: %s",ifp->trfile);
  302.         printf("\n");
  303.     } else
  304.         printf(" tracing off\n");
  305. }
  306.  
  307. /* shut down all trace files */
  308. void
  309. shuttrace()
  310. {
  311.     struct iface *ifp;
  312.  
  313.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next){
  314.         if(ifp->trfp != NULLFILE && ifp->trfp != stdout)
  315.             fclose(ifp->trfp);
  316.         if(ifp->trfile != NULLCHAR)
  317.             free(ifp->trfile);
  318.         ifp->trfile = NULLCHAR;
  319.         ifp->trfp = NULLFILE;
  320.     }
  321. }
  322.  
  323. /* Log messages of the form
  324.  * Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
  325.  */
  326. #if     defined(ANSIPROTO)
  327. void
  328. trace_log(struct iface *ifp,char *fmt, ...)
  329. {
  330.     va_list ap;
  331.     char *cp;
  332.     long t;
  333.  
  334.     if(ifp->trfp == NULLFILE)
  335.         return;
  336.  
  337.     t = secclock();
  338.     cp = ctime(&t);
  339.     rip(cp);
  340.     fprintf(ifp->trfp,"%s",cp);
  341.  
  342.     fprintf(ifp->trfp," - ");
  343.     va_start(ap,fmt);
  344.     vfprintf(ifp->trfp,fmt,ap);
  345.     va_end(ap);
  346.     fprintf(ifp->trfp,"\n");
  347. }
  348. #else
  349. /*VARARGS2*/
  350. void
  351. trace_log(ifp,fmt,arg1,arg2,arg3,arg4,arg5)
  352. struct iface *ifp;
  353. char *fmt;
  354. int arg1,arg2,arg3,arg4,arg5;
  355. {
  356.     char *cp;
  357.     long t;
  358.  
  359.     if(ifp->trfp == NULLFILE)
  360.         return;
  361.  
  362.     t = secclock();
  363.     cp = ctime(&t);
  364.     rip(cp);
  365.     fprintf(ifp->trfp,"%s",cp);
  366.  
  367.     fprintf(ifp->trfp," - ");
  368.     fprintf(ifp->trfp,fmt,arg1,arg2,arg3,arg4,arg5);
  369.     fprintf(ifp->trfp,"\n");
  370. }
  371. #endif
  372.  
  373.